//--------------------------------------------------------------------------
// 
//  Copyright (c) Chili Software.  All rights reserved. 
// 
//  File: RelationInfo.cs
//
//  Description: Contains the relation data for one relation.
// 
//--------------------------------------------------------------------------

using System;
using System.Reflection;
using System.Collections.Generic;
using Chili.Opf3.Relations;

namespace Chili.Opf3.Mapping
{
	/// <summary>
	/// Class that represents a relation of one persistent object with other.
	/// </summary>
	/// <remarks>
	/// This class represents a relation between two or more persistent objects with other persistent objects.
	/// </remarks>
	internal sealed class RelationInfo : IRelationInfo
	{
		private MemberInfo _member;
		private RelationAttribute _attribute;
		private RelatedPropertiesPairCollection _relatedProperties = new RelatedPropertiesPairCollection();
		private RelatedPropertiesPairCollection _weakRelatedProperties = new RelatedPropertiesPairCollection();
		private TypeMapping _parentMapping;
		private TypeMapping _weakMapping;
		private TypeMapping _childMapping;

		/// <summary>
		/// Creates a new instance of the <see cref="RelationInfo">RelationInfo Class</see>.
		/// </summary>
		/// <param name="member">The MemberInfo object that's type is a class inheriting from <see cref="ObjectHolderBase">ObjectHolderBase</see>.</param>
		/// <param name="attribute">The <see cref="RelationAttribute">RelationAttribute</see> specifying the relation between the two objects.</param>
		/// <param name="relatedPropertiesPairs">The list of related properties pairs.</param>
		internal RelationInfo(MemberInfo member, RelationAttribute attribute, IList<RelatedPropertiesPair> relatedPropertiesPairs)
		{
			_member = member;
			_attribute = attribute;

			foreach (RelatedPropertiesPair pair in relatedPropertiesPairs)
			{
				_relatedProperties.Add(pair);
			}
		}

		/// <summary>
		/// Creates a new instance of the <see cref="RelationInfo">RelationInfo Class</see>.
		/// </summary>
		/// <param name="member">The MemberInfo object that's type is a class inheriting from <see cref="ObjectHolderBase">ObjectHolderBase</see>.</param>
		/// <param name="attribute">The <see cref="RelationAttribute">RelationAttribute</see> specifying the relation between the two objects.</param>
		/// <param name="relatedPropertiesPairs">The list of related properties pairs.</param>
		/// <param name="weakRelatedPropertiesPairs">The list of weak related properties pairs.</param>
		internal RelationInfo(MemberInfo member, RelationAttribute attribute, IList<RelatedPropertiesPair> relatedPropertiesPairs, IList<RelatedPropertiesPair> weakRelatedPropertiesPairs)
			: this(member, attribute, relatedPropertiesPairs)
		{
			foreach (RelatedPropertiesPair pair in weakRelatedPropertiesPairs)
			{
				_weakRelatedProperties.Add(pair);
			}
		}

		/// <summary>
		/// Returns the class that inherits from <see cref="ObjectHolderBase">ObjectHolderBase</see>. Classes
		/// inheriting from that class are holding related objects.
		/// </summary>
		/// <param name="obj">The instance that's <see cref="ObjectHolderBase">ObjectHolderBase</see> should be returned.</param>
		public ObjectHolderBase GetObjectHolder(object obj)
		{
			if (_member.MemberType == MemberTypes.Field)
				return (ObjectHolderBase)((FieldInfo)_member).GetValue(obj);
			return (ObjectHolderBase)((PropertyInfo)_member).GetValue(obj, null);
		}

		/// <summary>
		/// Returns the <see cref="RelationAttribute">RelationAttribute</see> of the current relation.
		/// </summary>
		public RelationAttribute RelationAttribute
		{
			get { return _attribute; }
		}

		/// <summary>
		/// Returns a list of related properties between two objects. This list contains <see cref="IRelatedPropertiesPair">IRelatedPropertiesPair</see> 
		/// interfaces that contain the related properties in the two objects.
		/// </summary>
		public IRelatedPropertiesPairCollection RelatedProperties
		{
			get { return _relatedProperties; }
		}

		/// <summary>
		/// Returns a list of weak related properties between two objects. This list contains <see cref="IRelatedPropertiesPair">IRelatedPropertiesPair</see> 
		/// interfaces that contain the weak related properties in the two objects.
		/// </summary>
		public IRelatedPropertiesPairCollection WeakRelatedProperties
		{
			get { return _weakRelatedProperties; }
		}

		/// <summary>
		/// Specifies the <see cref="TypeMapping">TypeMapping</see> of the parent type.
		/// </summary>
		public TypeMapping ParentTypeMapping
		{
			get { return _parentMapping; }
			set { _parentMapping = value; }
		}

		/// <summary>
		/// Specifies the <see cref="TypeMapping">TypeMapping</see> of the child type.
		/// </summary>
		public TypeMapping ChildTypeMapping
		{
			get { return _childMapping; }
			set { _childMapping = value; }
		}

		/// <summary>
		/// Specifies the <see cref="TypeMapping">TypeMapping</see> of the weak persistent type. May be null 
		/// if no many-to-many relation has been specified.
		/// </summary>
		public TypeMapping WeakTypeMapping
		{
			get { return _weakMapping; }
			set { _weakMapping = value; } 
		}
	}
}
